#pragma once
#include<iostream>
#include<string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <jsoncpp/json/json.h>
using namespace std;

#define SEP " "
#define SEP_LEN strlen(SEP)//strlen统计'\0'之前的字符个数，而sizeof统计的是所占内存的空间大小，使用sizeof会越界出问题
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)

enum {
    NONE=0,
    DIV_ZERO,
    MOD_ZERO,
    OP_ERR
};
//"x op y"->"text_len"\r\n"x op y"\r\n---給内容加上报头
std::string enLength(const std::string& text)//协议定制
{
    std::string send_str=to_string(text.size());
    send_str+=LINE_SEP;
    send_str+=text;
    send_str+=LINE_SEP;

    return send_str;
}
//"text_len"\r\n"x op y"\r\n -> "x op y"---去掉报头，取出里面的内容
bool deLength(const std::string& str,string* ret)//协议定制
{
    auto it=str.find(LINE_SEP);//找到报头
    if(it==std::string::npos) return false;//如果没找到则直接返回

    int len=stoi(str.substr(0,it));//取出字符串的长度
    *ret=str.substr(it+LINE_SEP_LEN,len);//取出数据
    return true;
}

class Request
{
public:
Request():_x(0),_y(0),_op(0){}
Request(int x,int y,int op):_x(x),_y(y),_op(op){}

bool Serialize(std::string* out)//序列化，将传入的x op y转化为字符串"x op y"
{
#ifdef MYPRO
    *out="";
    *out+=to_string(_x);
    *out+=SEP;
    *out+=to_string(_op);
    *out+=SEP;
    *out+=to_string(_y);
#else
Json::Value root;//json的对象是键值对[key,value]
root["first"]=_x;//int类型被设置进json的键值对时自动转换为string类型
root["second"]=_y;
root["oper"]=_op;

Json::FastWriter writer;

*out=writer.write(root);//调用接口序列化返回值为字符串

#endif

    return true;
}

bool Deserialize( const string& origin)//反序列化，将传过来的字符串拆出来传参給_x _op _y
{//"_xSEP_opSEP_y"-> _x,_op,_y

#ifdef MYPRO
    auto leftit=origin.find(SEP);
    cout<<"Deserialize找到了leftSEP: "<<leftit<<endl;
    auto rightit=origin.rfind(SEP);
    cout<<"Deserialize找到了rightSEP: "<<rightit<<endl;
    if(leftit==string::npos|| rightit==string::npos) return false;

    if(leftit==rightit) return false;
    int opsize=rightit-leftit-1;
    cout<<"opsize: "<<opsize<<endl;
//1 43 1--leftit=1,rightit=4,opsize=rightit-leftit-1=4-1-1=2;
//1 3 1--leftit=1,right=3,opsize=rightit-leftit-1=3-1-1=1
   // if(rightit-(leftit+SEP_LEN)!=1) return false;
    if(rightit-(leftit+SEP_LEN)!=opsize) return false;
    //+号ASCII码是43，从char转int被解析成43即stringlen为两位,这里的运算rightit-(leftit+SEP_LEN)!=1就出问题
//4-(1+1)==2;3-(1+1)=1
    std::string origin_x=origin.substr(0,leftit);
    std::string origin_y=origin.substr(rightit+SEP_LEN);
    if(origin_x.empty()) return false;

    if(origin_y.empty()) return false;

    cout<<"origin_x: "<<origin_x<<" origin_y: "<<origin_y<<endl;
    _x=stoi(origin_x);
    int opf=stoi(origin.substr(leftit,rightit));
    _op=opf;
    cout<<"opf: "<<opf<<"_op: "<<_op<<endl;
    _y=stoi(origin_y);
#else
Json::Value root;
Json::Reader reader;
reader.parse(origin,root);//反序列化，将字符串中的协议字符串填进对象对应的元素中

_x=root["first"].asInt();
_y=root["second"].asInt();
_op=root["oper"].asInt();
#endif
    return true;

}
    public:
    int _x;
    int _y;
    char _op;
};

class Response
{
public:
Response():_exitcode(0),_result(0){}
Response(int exitcode,int result):_exitcode(exitcode),_result(result){}
bool Serialize(string*out)//序列化
{//_exitcode _result ->"_exitcodeSEP_result"
#ifdef MYPRO
*out="";
*out+=to_string(_exitcode);
*out+=SEP;
*out+=to_string(_result);
#else
Json::Value root;
root["exitcode"]=_exitcode;
root["result"]=_result;

Json::FastWriter writer;
*out= writer.write(root);
#endif

return true;
}

bool Deserialize(const string& in)//反序列化
{//_exitcodeSEP_result"->_exitcode _result

#ifdef MYPRO
auto pos=in.find(SEP);
if(pos==string::npos) return false;

string excstr=in.substr(0,pos);
string resstr=in.substr(pos+SEP_LEN);
if(excstr.empty()||resstr.empty()) return false;

_exitcode=stoi(excstr);
_result=stoi(resstr);

#else
Json::Value root;
Json::Reader reader;
reader.parse(in,root);
_exitcode=root["exitcode"].asInt();
_result=root["result"].asInt();
#endif
return true;

}

public:
int _exitcode;//退出码
int _result;//结果
};

//"text_len"\r\n"x op y"\r\n
bool recvPackage(int sock,string& inbuffer,string*out)
{
char buffer[1024];

while(true)
{
ssize_t  s=recv(sock,buffer,sizeof(buffer)-1,0);
if(s>0)
{
    buffer[s]=0;
    inbuffer+=buffer;
    auto pos=inbuffer.find(LINE_SEP);
    if(pos==string::npos)continue;//没找到报头和有效载荷之间的分隔符---如果字节流式的报文没读全就继续读
    string text_len=inbuffer.substr(0,pos);//报头是有效载荷的长度
    int len=stoi(text_len);
    
    int totallen=text_len.size()+LINE_SEP_LEN*2+len;//整个报文的长度
    if(inbuffer.size()<totallen) 
    {
        cout<<"输入的消息不完整,请继续输入.continue..."<<endl;
        continue;//报文没读完继续读
    }
    
    cout<<"处理前的inbuffer: \n"<<inbuffer<<endl;

    *out=inbuffer.substr(0,totallen);
    inbuffer.erase(0,totallen);

    cout<<"处理后的inbuffer: \n"<<inbuffer<<endl;

    break;
}
else return false;
}

return true;

}